﻿using Bricks.Injecting;
using Bricks.Logging;
using Bricks.Unity.Injecting;
using Microsoft.Practices.Unity;
using Motar.Modularity;

namespace Motar.UnityExtensions
{

    /// <summary>
    /// 
    /// </summary>
    public class UnityBootstrapperExtension : UnityContainerExtension
    {

        /// <summary>
        /// 
        /// </summary>
        protected override void Initialize()
        {
            if (Container.Configure(GetType()) == this)
            {
                //
                ConfigureContainer();

                //
                ConfigureContainerFacade();

                //
                ConfigureLogger();

                //
                ConfigureModuleCatalog();

                //
                ConfigureModularity();

                //
                ConfigureOthers();

                //
                ConfigureApplication();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual void ConfigureContainer()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual void ConfigureContainerFacade()
        {
            RegisterIfMissing<IContainerFacade, UnityContainerFacade>(true);

            RegisterIfMissing<IContainerRegistryFacade, UnityContainerRegistryFacade>(true);
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual void ConfigureLogger()
        {
            RegisterIfMissing<ILoggerFacade, NullLoggerFacade>(true);
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual void ConfigureModuleCatalog()
        {
            RegisterIfMissing<IModuleCatalog, ModuleCatalog>(true);
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual void ConfigureModularity()
        {
            RegisterIfMissing<IModuleInitializer, ModuleInitializer>(true);

            RegisterIfMissing<IModuleManager, ModuleManager>(true);
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual void ConfigureOthers()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual void ConfigureApplication()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TFrom"></typeparam>
        /// <typeparam name="TTo"></typeparam>
        /// <param name="registerAsSingleton"></param>
        protected virtual void RegisterIfMissing<TFrom, TTo>(bool registerAsSingleton, params InjectionMember[] injectionMembers) where TTo : TFrom
        {
            if (!Container.IsRegistered<TFrom>())
            {
                if (registerAsSingleton)
                {
                    Container.RegisterType<TFrom, TTo>(new ContainerControlledLifetimeManager(), injectionMembers);
                }
                else
                {
                    Container.RegisterType<TFrom, TTo>(injectionMembers);
                }
            }
        }
    }
}
